#include "DisconnectLogger.h"
#include <QDebug>

DisconnectLogger* DisconnectLogger::m_instance = nullptr;

DisconnectLogger* DisconnectLogger::instance() {
    if (!m_instance) {
        static QMutex mutex;
        QMutexLocker locker(&mutex);
        if (!m_instance) {
            m_instance = new DisconnectLogger();
        }
    }
    return m_instance;
}

DisconnectLogger::DisconnectLogger(QObject *parent) : QObject(parent) {
    initializeLogFile();
}

DisconnectLogger::~DisconnectLogger() {
    QMutexLocker locker(&m_mutex);
    if (m_logStream) {
        delete m_logStream;
        m_logStream = nullptr;
    }
    if (m_logFile) {
        if (m_logFile->isOpen()) {
            m_logFile->close();
        }
        delete m_logFile;
        m_logFile = nullptr;
    }
}

void DisconnectLogger::initializeLogFile() {
    QMutexLocker locker(&m_mutex);
    
    QString logDir = QCoreApplication::applicationDirPath() + "/logs";
    QDir dir;
    if (!dir.exists(logDir)) {
        dir.mkpath(logDir);
    }
    
    m_currentLogFileName = getLogFileName();
    m_logFile = new QFile(m_currentLogFileName);
    
    if (!m_logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
        qDebug() << "无法打开断开连接日志文件: " << m_currentLogFileName;
        delete m_logFile;
        m_logFile = nullptr;
        m_logStream = nullptr;
        return;
    }
    
    m_logStream = new QTextStream(m_logFile);
    
    // 写入文件头
    *m_logStream << "\n=== Disconnect Log Started ===\n";
    *m_logStream << "Start Time: " << QDateTime::currentDateTime().toString(Qt::ISODate) << "\n";
    *m_logStream << "========================================\n";
    m_logStream->flush();
}

QString DisconnectLogger::getLogFileName() const {
    QString logDir = QCoreApplication::applicationDirPath() + "/logs";
    QString currentDate = QDateTime::currentDateTime().toString("yyyy-MM-dd");
    return QString("%1/disconnect_log_%2.log").arg(logDir).arg(currentDate);
}

QString DisconnectLogger::disconnectTypeToString(DisconnectType type) const {
    switch (type) {
        case DisconnectType::HeartbeatTimeout: return "HeartbeatTimeout";
        case DisconnectType::RegisterTimeout: return "RegisterTimeout";
        case DisconnectType::DatabaseTimeout: return "DatabaseTimeout";
        case DisconnectType::ManualDisconnect: return "ManualDisconnect";
        case DisconnectType::SocketError: return "SocketError";
        case DisconnectType::NetworkError: return "NetworkError";
        case DisconnectType::UserRequest: return "UserRequest";
        case DisconnectType::SystemShutdown: return "SystemShutdown";
        default: return "Unknown";
    }
}

QString DisconnectLogger::disconnectResultToString(DisconnectResult result) const {
    switch (result) {
        case DisconnectResult::Success: return "Success";
        case DisconnectResult::Failed: return "Failed";
        case DisconnectResult::PartialSuccess: return "PartialSuccess";
        case DisconnectResult::Timeout: return "Timeout";
        case DisconnectResult::Error: return "Error";
        default: return "Unknown";
    }
}

QJsonObject DisconnectLogger::entryToJson(const DisconnectLogEntry& entry) const {
    QJsonObject json;
    json["timestamp"] = entry.timestamp;
    json["disconnect_type"] = entry.disconnectTypeStr;
    json["trigger_reason"] = entry.triggerReason;
    json["connection_id"] = entry.connectionId;
    json["user_id"] = entry.userId;
    json["robot_sn"] = entry.robotSN;
    json["client_address"] = entry.clientAddress;
    json["client_port"] = entry.clientPort;
    json["result"] = entry.resultStr;
    json["context_info"] = entry.contextInfo;
    json["connection_duration_ms"] = entry.connectionDuration;
    json["heartbeat_count"] = entry.heartbeatCount;
    json["additional_info"] = entry.additionalInfo;
    return json;
}

void DisconnectLogger::logDisconnect(const DisconnectLogEntry& entry) {
    QMutexLocker locker(&m_mutex);
    
    if (!m_logStream) {
        qDebug() << "日志流未初始化，无法记录断开连接日志";
        return;
    }
    
    // 检查是否需要创建新的日志文件（跨天情况）
    QString newLogFileName = getLogFileName();
    if (newLogFileName != m_currentLogFileName) {
        // 关闭当前日志文件
        if (m_logFile->isOpen()) {
            m_logFile->close();
        }
        delete m_logFile;
        delete m_logStream;
        
        // 重新初始化日志文件
        m_currentLogFileName = newLogFileName;
        m_logFile = new QFile(m_currentLogFileName);
        if (!m_logFile->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text)) {
            qDebug() << "无法打开新的断开连接日志文件: " << m_currentLogFileName;
            delete m_logFile;
            m_logFile = nullptr;
            m_logStream = nullptr;
            return;
        }
        m_logStream = new QTextStream(m_logFile);
    }
    
    // 将日志条目转换为JSON格式并写入文件
    QJsonObject jsonEntry = entryToJson(entry);
    QJsonDocument doc(jsonEntry);
    QByteArray jsonData = doc.toJson(QJsonDocument::Compact);
    
    *m_logStream << jsonData << "\n";
    m_logStream->flush();
    
    // 同时输出到调试控制台
    qDebug() << QString("[DISCONNECT_LOG] %1 - %2 - %3 - %4:%5 - SN:%6 - Result:%7")
                .arg(entry.timestamp)
                .arg(entry.disconnectTypeStr)
                .arg(entry.triggerReason)
                .arg(entry.clientAddress)
                .arg(entry.clientPort)
                .arg(entry.robotSN)
                .arg(entry.resultStr);
}

void DisconnectLogger::logDisconnect(DisconnectType type, const QString& reason, 
                                     const QString& connectionId, const QString& robotSN,
                                     const QString& clientAddress, int clientPort,
                                     DisconnectResult result, const QString& context,
                                     qint64 connectionDuration, int heartbeatCount,
                                     const QString& additionalInfo) {
    DisconnectLogEntry entry;
    entry.timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
    entry.disconnectType = type;
    entry.disconnectTypeStr = disconnectTypeToString(type);
    entry.triggerReason = reason;
    entry.connectionId = connectionId;
    entry.userId = "";
    entry.robotSN = robotSN;
    entry.clientAddress = clientAddress;
    entry.clientPort = clientPort;
    entry.result = result;
    entry.resultStr = disconnectResultToString(result);
    entry.contextInfo = context;
    entry.connectionDuration = connectionDuration;
    entry.heartbeatCount = heartbeatCount;
    entry.additionalInfo = additionalInfo;
    
    logDisconnect(entry);
}

void DisconnectLogger::logHeartbeatTimeout(const QString& robotSN, const QString& clientAddress, 
                                           int consecutiveTimeouts, qint64 connectionDuration, int heartbeatCount) {
    QString reason = QString("连续心跳超时次数: %1").arg(consecutiveTimeouts);
    QString context = QString("心跳超时检测 - 连续超时: %1 次").arg(consecutiveTimeouts);
    logDisconnect(DisconnectType::HeartbeatTimeout, reason, "", robotSN, clientAddress, -1,
                  DisconnectResult::Success, context, connectionDuration, heartbeatCount);
}

void DisconnectLogger::logRegisterTimeout(const QString& clientAddress, qint64 connectionDuration) {
    QString reason = "设备注册超时";
    QString context = "设备在60秒内未完成注册流程";
    logDisconnect(DisconnectType::RegisterTimeout, reason, "", "", clientAddress, -1,
                  DisconnectResult::Success, context, connectionDuration, 0);
}

void DisconnectLogger::logDatabaseTimeout(const QString& robotSN, const QString& lastPing, qint64 connectionDuration) {
    QString reason = "数据库超时检测";
    QString context = QString("最后心跳时间: %1").arg(lastPing);
    logDisconnect(DisconnectType::DatabaseTimeout, reason, "", robotSN, "", -1,
                  DisconnectResult::Success, context, connectionDuration, 0);
}

void DisconnectLogger::logManualDisconnect(const QString& robotSN, const QString& clientAddress, 
                                         const QString& operatorInfo, qint64 connectionDuration) {
    QString reason = QString("手动断开操作 - %1").arg(operatorInfo);
    QString context = "通过disconnectRobotBySN接口主动断开";
    logDisconnect(DisconnectType::ManualDisconnect, reason, "", robotSN, clientAddress, -1,
                  DisconnectResult::Success, context, connectionDuration, 0, operatorInfo);
}

void DisconnectLogger::logSocketError(const QString& robotSN, const QString& clientAddress, 
                                    const QString& errorString, qint64 connectionDuration) {
    QString reason = QString("Socket错误: %1").arg(errorString);
    QString context = "网络连接异常导致断开";
    logDisconnect(DisconnectType::SocketError, reason, "", robotSN, clientAddress, -1,
                  DisconnectResult::Error, context, connectionDuration, 0, errorString);
}

void DisconnectLogger::logUserRequest(const QString& userId, const QString& robotSN, 
                                    const QString& reason, qint64 connectionDuration) {
    QString context = QString("用户请求断开连接 - 用户ID: %1").arg(userId);
    logDisconnect(DisconnectType::UserRequest, reason, "", robotSN, "", -1,
                  DisconnectResult::Success, context, connectionDuration, 0, userId);
}